package com.crl.rcdp.gateway.test;

import com.cars.util.json.JsonUtil;
import com.crl.rcdp.gateway.filter.FilterUtil;
import com.crl.rcdp.gateway.util.IPUtil;
import com.crl.rcdp.sys.model.SysLog;
import com.crl.rcdp.sys.service.SysLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.Date;

/**
 * @author: demo
 * @date: 2020年7月2日
 * @Document : 请求记录过滤器
 */
@Slf4j
//@Component
public class RecordGlobalFilter implements GlobalFilter, Ordered {
    @Autowired
    private SysLogService sysLogService;

    private static final String SUPPORT_SCHEME_HTTP = "http";
    private static final String SUPPORT_SCHEME_HTTPS = "https";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest originalRequest = exchange.getRequest();
        URI originalRequestUrl = originalRequest.getURI();
        // 只记录http的请求
        String scheme = originalRequestUrl.getScheme();
        if ((!SUPPORT_SCHEME_HTTP.equals(scheme) && !SUPPORT_SCHEME_HTTPS.equals(scheme))) {
            return chain.filter(exchange);
        }
        RecordDO record = new RecordDO(RouteIdUtil.nextStringId());
        Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
        URI gatewayUri = route.getUri();
        record.setGatewayAddress(FilterUtil.getUriAddress(gatewayUri));

        String authorization = exchange.getRequest().getHeaders().getFirst("Authorization");//获取authorization
        String appid = exchange.getRequest().getHeaders().getFirst("appid");//appid
        String accessToken = exchange.getRequest().getHeaders().getFirst("accessToken");//accessToken
        Integer authType = FilterUtil.getAuthType(authorization, accessToken, appid);//授权方式
        String owner = FilterUtil.getOwner(authorization, accessToken, appid);
        record.setAuthType(authType);
        record.setOwner(owner);
        /**
         * 重写request 和response
         */
        RecordHttpRequestDecorator recordRequest = new RecordHttpRequestDecorator(exchange.getRequest());
        RecordHttpResponseDecorator recordResponse = new RecordHttpResponseDecorator(exchange.getResponse(), record, sysLogService);
        ServerWebExchange recordExchange = exchange.mutate().request(recordRequest).response(recordResponse).build();
        return recorderOriginalRequest(recordExchange, record).then(chain.filter(recordExchange)).then();
    }

    /**
     * 记录请求信息
     * 获取请求信息  ==>record
     * url method header param startTime
     *
     * @param exchange
     * @param record
     * @return
     */
    private Mono<Void> recorderOriginalRequest(ServerWebExchange exchange, RecordDO record) {
        ServerHttpRequest request = exchange.getRequest();
        URI requestUri = request.getURI();
        record.setUrl(requestUri.getRawPath());
        record.setRequestAddress(FilterUtil.getUriAddress(requestUri));
        record.setMethod(request.getMethod().name());
        HttpHeaders headers = request.getHeaders();
        record.setClientAddress(RecordTool.getClientIp(request));
        record.setRequestHeader(JsonUtil.toStr(headers));
        record.setStartTime(new Date());
        Charset requestCharset = RecordTool.getCharsetRecord(headers);
        Mono<Void> result = Mono.empty();
        try {
            log.info("请求信息==>{}", record);
//			recordService.addRecord(record);
            System.out.println("请求信息：" + record.toString());

        } catch (Exception e) {
            e.printStackTrace();
            log.error("record请求信息error !==>{}", e.getMessage());
        }
        if (requestCharset != null) {
            result = DataBufferUtils.join(request.getBody()).doOnNext(buffer -> {
                CharBuffer charBuffer = requestCharset.decode(buffer.asByteBuffer());
                record.setRequestParam(charBuffer.toString());
                try {
                    log.info("更新请求参数记录==>{}", record);
                    System.out.println("修改信息：" + record.toString());
                    SysLog sysLog = new SysLog();
                    String servletPath = request.getPath().toString();//获取请求url
                    String authorization = request.getHeaders().getFirst("Authorization");//获取authorization
                    String appid = request.getHeaders().getFirst("appid");//appid
                    String accessToken = request.getHeaders().getFirst("accessToken");//accessToken
                    sysLog.setClientIp(IPUtil.getIpAddress(exchange.getRequest()));//ip地址
                    sysLog.setAuthType(FilterUtil.getAuthType(authorization, accessToken, appid));//授权方式
                    sysLog.setPath(servletPath);//请求地址
                    sysLog.setServiceName(exchange.getAttribute("SERVICE_NAME"));
                    sysLog.setRequestParam(record.getRequestParam());//请求参数
                    sysLog.setOwner(FilterUtil.getOwner(authorization, accessToken, appid));//owner
                    sysLogService.add(sysLog);
//                    record.setLogId(logid);
                } catch (Exception e) {
                    log.error("更新请求参数error !==>{}", e.getMessage());
                }

                DataBufferUtils.release(buffer);
            }).then();
        }
        return result;
    }

    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }

}